package com.codeyang.mocktest2.mockit;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import static org.mockito.Mockito.*;

/**
 * 描述:
 * 20 @Spy 的缺陷
 *
 * @author shengyang5
 * @version 2021/7/22 15:26
 */
class ExampleService2 {

    int add(int a, int b) {
        return a + b;
    }

}

public class SpyStudy02 {
    /**
     * mockito 1.0版本中使用@Spy监视接口类，会报错，2.0版本中不会报错，但是不支持接口类、内部类、抽象类（这是个大坑）
     *  对于@Spy，如果发现修饰的变量是 null，会自动调用类的无参构造函数来初始化
     *
     * 注意：
     * @Spy 如果是修饰接口的话，不能调用的到真实的方法，而且还不报错
     *      如果要真实模拟，必须指定到接口的实现类，而且实现类的其他 资源类，你也需要手动的@mock或者@spy加入
     *      不能自动的处理类里的Bean的依赖关系
     */


    /**
     * 写法1
     *
     * @Spy private ExampleService spyExampleService;
     * 写法2
     * @Spy private ExampleService spyExampleService = new ExampleService();
     * 注意: 如果没有无参的构造方法那么就要手动new对象
     */
    @Spy
    private ExampleService2 spyExampleService2;

    @Test
    public void test_spy() {

        MockitoAnnotations.initMocks(this);

        Assert.assertEquals(3, spyExampleService2.add(1, 2));

        when(spyExampleService2.add(1, 2)).thenReturn(10);
        Assert.assertEquals(10, spyExampleService2.add(1, 2));

    }

    /**
     * @Spy 可以修饰接口，抽象类等 但是调用方法不报错，返回默认值
     */
    @Spy
    private Isa isa;

    @Test
    public void isaTest() {

        MockitoAnnotations.initMocks(this);

        String name = isa.loadName();
        System.out.println(name);

    }

    /**
     * @Spy 本身需要支持到接口具体实现类
     */
    @Spy
    private IsaImpl isaImpl;

    @Test
    public void isaImplTest() {

        MockitoAnnotations.initMocks(this);

        String name = isaImpl.loadName();
        System.out.println(name);

    }


}

interface Isa {
    String loadName();
}

class IsaImpl implements Isa {
    @Override
    public String loadName() {
        return "1111";
    }
}
